Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Security.Permissions

Namespace C4F.DevKit.PreviewHandler.PreviewHandlerHostSample
	Public Partial Class ExplorerForm
		Inherits Form
		Public Const SHGFI_ICON As UInteger = &H100 ' Gets the icon
		Public Const SHGFI_DISPLAYNAME As UInteger = &H200 ' Gets the Display name
		Public Const SHGFI_TYPENAME As UInteger = &H400 ' Gets the type name
		Public Const SHGFI_LARGEICON As UInteger = &H0 ' Large icon
		Public Const SHGFI_SMALLICON As UInteger = &H1 ' Small icon

		Private Const IMAGE_FOLDER_KEY As String = "Folder"
		Private Const MAX_LOCATION_HISTORY As Integer = 5
		Private _locations As List(Of String) = New List(Of String)(MAX_LOCATION_HISTORY)
		Private _locationPosition As Integer = 0
		Private isForward As Boolean = False
		Private isBack As Boolean = False

		Public Sub New()
			InitializeComponent()
		End Sub

		#Region "Methods"

		#Region "Private"

		Private Sub InitializeFolderList()
			Dim drives As String() = Environment.GetLogicalDrives()

			For Each drive As String In drives
				Dim node As TreeNode = New TreeNode()
				node.Text = drive
				node.Name = drive

				trvFolderList.Nodes.Add(node)
			Next drive
		End Sub

		Private Sub JumpToNode(ByVal path As String)
			trvFolderList.SelectedNode = trvFolderList.SelectedNode.Nodes(path)
		End Sub

		Private Function IsDirectory(ByVal info As FileSystemInfo) As Boolean
			Return (info.Attributes And FileAttributes.Directory) = FileAttributes.Directory
		End Function

		Private Function IsHidden(ByVal info As FileSystemInfo) As Boolean
			Return (info.Attributes And FileAttributes.Hidden) = FileAttributes.Hidden
		End Function

		#End Region ' Private

		#Region "Protected"

		#End Region ' Protected

		#Region "Eventhandlers"

		Private Sub ExplorerForm_Load(ByVal sender As Object, ByVal e As EventArgs)
			InitializeFolderList()
		End Sub

		Private Sub trvFolderList_AfterSelect(ByVal sender As Object, ByVal e As TreeViewEventArgs)
			Try

				Dim dirList As DirectoryInfo() = New DirectoryInfo(CStr(e.Node.Name)).GetDirectories()

				lvwFiles.Items.Clear()
				imageList1.Images.Clear()
				e.Node.Nodes.Clear()

				For Each dir As DirectoryInfo In dirList
					If (Not IsHidden(dir)) Then
						Dim info As SHFILEINFO = ExplorerForm.GetFileInfo(dir.FullName)
						imageList1.Images.Add(dir.Name, System.Drawing.Icon.FromHandle(info.hIcon))

						Dim item As ListViewItem = lvwFiles.Items.Add(dir.Name, dir.Name)

						item.Tag = dir.FullName

						Dim node As TreeNode = New TreeNode()
						node.Text = dir.Name
						node.Name = dir.FullName
						node.ImageKey = IMAGE_FOLDER_KEY
						e.Node.Nodes.Add(node)
					End If
				Next dir

				Dim fileList As FileInfo() = New DirectoryInfo(CStr(e.Node.Name)).GetFiles()

				For Each file As FileInfo In fileList
					If (Not IsHidden(file)) Then
						Dim info As SHFILEINFO = ExplorerForm.GetFileInfo(file.FullName)

						imageList1.Images.Add(file.Name, System.Drawing.Icon.FromHandle(info.hIcon))

						Dim item As ListViewItem = lvwFiles.Items.Add(file.Name, file.Name)
						item.SubItems.Add(New ListViewItem.ListViewSubItem(item, String.Format("{0} {1}", file.LastWriteTime.ToShortDateString(), file.LastWriteTime.ToShortTimeString())))
						item.SubItems.Add(New ListViewItem.ListViewSubItem(item, info.szTypeName))
						item.SubItems.Add(New ListViewItem.ListViewSubItem(item, (file.Length / 1000).ToString("N0") & " KB"))
						item.Tag = file.FullName
					End If
				Next file

				txtLocation.Text = trvFolderList.SelectedNode.Name

				If (Not isBack) AndAlso (Not isForward) Then
					If _locationPosition < _locations.Count Then
						Dim i As Integer = _locationPosition
						Do While i < _locations.Count
							_locations.RemoveAt(i)
							i += 1
						Loop
					End If
					If _locations.Count = MAX_LOCATION_HISTORY Then
						_locations.RemoveAt(0)
						_locationPosition -= 1
					End If

					_locations.Add(txtLocation.Text)
					_locationPosition += 1
				End If
				If _locationPosition = 1 Then
					tsbBack.Enabled = False
				Else
					tsbBack.Enabled = True
				End If
				If _locations.Count > _locationPosition Then
					tsbForward.Enabled = True
				Else
					tsbForward.Enabled = False
				End If
				If trvFolderList.SelectedNode.Parent Is Nothing Then
					tsbUp.Enabled = False
				Else
					tsbUp.Enabled = True
				End If
				isBack = False
				isForward = False
			Catch e1 As Exception
			End Try


		End Sub

		Private Sub lvwFiles_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
			If lvwFiles.SelectedItems.Count = 1 Then
				Dim selectedItem As ListViewItem = lvwFiles.SelectedItems(0)
				Dim file As FileInfo = New FileInfo(selectedItem.Tag.ToString())

				If (Not IsDirectory(file)) Then
					Try
						PreviewHandlerHostControl1.FilePath = file.FullName
					Catch anexception As Exception

					End Try
				End If
			End If
		End Sub

		Private Sub lvwFiles_DoubleClick(ByVal sender As Object, ByVal e As EventArgs)
			Try
				If lvwFiles.SelectedItems.Count = 1 Then
					Dim path As String = lvwFiles.SelectedItems(0).Tag.ToString()

					If Directory.Exists(path) Then
						JumpToNode(path)
					End If

				End If
			Catch e1 As Exception
				' TODO: Add error message somewhere
			End Try
		End Sub

		Private Sub tsbUp_Click(ByVal sender As Object, ByVal e As EventArgs)
			Try
				If Not trvFolderList.SelectedNode.Parent Is Nothing Then
					trvFolderList.SelectedNode = trvFolderList.SelectedNode.Parent
				End If
			Catch e1 As Exception
				' TODO: Do something about error
			End Try
		End Sub

		#End Region ' EventHandlers

		#End Region ' Methods

		<DllImport("shell32.dll")> _
		Public Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbSizeFileInfo As UInteger, ByVal uFlags As UInteger) As IntPtr
		End Function

		<SecurityPermission(SecurityAction.LinkDemand, Flags := SecurityPermissionFlag.UnmanagedCode)> _
		Public Shared Function GetFileInfo(ByVal path As String) As SHFILEINFO
			Dim info As SHFILEINFO = New SHFILEINFO()
			Dim icon As IntPtr

			icon = SHGetFileInfo(path, 0, info, CUInt(Marshal.SizeOf(info)), SHGFI_ICON Or SHGFI_TYPENAME Or SHGFI_SMALLICON)

			Return info
		End Function

		Private Sub txtLocation_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
			If e.KeyCode = Keys.Enter Then
				If trvFolderList.Nodes.Find(txtLocation.Text, True).Length > 0 Then
					trvFolderList.SelectedNode = trvFolderList.Nodes.Find(txtLocation.Text, True)(0)
				End If
			End If
		End Sub

		Private Sub tsbGo_Click(ByVal sender As Object, ByVal e As EventArgs)
			If trvFolderList.Nodes.Find(txtLocation.Text, True).Length > 0 Then
				trvFolderList.SelectedNode = trvFolderList.Nodes.Find(txtLocation.Text, True)(0)
			End If

		End Sub

		Private Sub tsbBack_Click(ByVal sender As Object, ByVal e As EventArgs)
			If _locationPosition > 1 AndAlso trvFolderList.Nodes.Find(_locations(_locationPosition-1), True).Length > 0 Then
				isBack = True
				_locationPosition -= 1
				trvFolderList.SelectedNode = trvFolderList.Nodes.Find(_locations(_locationPosition - 1), True)(0)
			End If

		End Sub

		Private Sub tsbForward_Click(ByVal sender As Object, ByVal e As EventArgs)
			If (_locations.Count > _locationPosition) AndAlso trvFolderList.Nodes.Find(_locations(_locationPosition), True).Length > 0 Then
				isForward = True
				_locationPosition += 1
				trvFolderList.SelectedNode = trvFolderList.Nodes.Find(_locations(_locationPosition-1), True)(0)
			End If

		End Sub
	End Class

	Public Structure SHFILEINFO
		Public hIcon As IntPtr
		Public iIcon As IntPtr
		Public dwAttributes As UInteger
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 260)> _
		Public szDisplayName As String
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 80)> _
		Public szTypeName As String
	End Structure
End Namespace